package com.monkey.web.platform.controller;

import com.monkey.core.domain.auth.UserResourcePermission;
import com.monkey.core.domain.organization.Organization;
import com.monkey.core.domain.permission.Permission;
import com.monkey.core.domain.resource.Menu;
import com.monkey.core.domain.role.Role;
import com.monkey.core.domain.user.User;
import com.monkey.core.domain.user.UserOnlineHistory;
import com.monkey.core.domain.user.UserStatus;
import com.monkey.core.domain.user.UserStatusHistory;
import com.monkey.core.plugin.dto.MonkeyDto;
import com.monkey.core.plugin.web.validator.ConstraintType;
import com.monkey.core.plugin.web.validator.ParameterConstraint;
import com.monkey.core.plugin.web.validator.ParameterConstraints;
import com.monkey.core.repository.search.SearchOperator;
import com.monkey.core.repository.search.Searchable;
import com.monkey.core.web.response.MonkeyResponseDto;
import com.monkey.utils.MonkeyUtils;
import com.monkey.web.bind.annotation.CurrentUser;
import com.monkey.web.dto.request.user.ModifyUserPasswordDto;
import com.monkey.web.dto.response.user.LoadUserLoginHistoriesResponseJSONDto;
import com.monkey.web.platform.service.OrganizationService;
import com.monkey.web.platform.service.UserOnlineHistoryService;
import com.monkey.web.platform.service.UserService;
import com.monkey.web.platform.service.UserStatusHistoryService;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import javax.validation.Valid;
import java.util.List;

/**
 * Created by silentwu on 2015/6/24.
 */
@Controller
@RequestMapping(value = "/m", produces = {MediaType.APPLICATION_JSON_VALUE})
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private OrganizationService organizationService;
    @Autowired
    private UserStatusHistoryService userStatusHistoryService;
    @Autowired
    private UserOnlineHistoryService userOnlineHistoryService;

    @ParameterConstraints(value = {
            @ParameterConstraint(name = "orgId", constraintType = {ConstraintType.NotBlank}, notBlank = @NotBlank(message = "所属组织必填")),
            @ParameterConstraint(name = "account", constraintType = {ConstraintType.Length},
                    length = @Length(min = 3, max = 10, message = "登录帐号的长度范围[3,10]")),
            @ParameterConstraint(name = "email", constraintType = {ConstraintType.NotBlank}, notBlank = @NotBlank(message = "邮箱必填")),
            @ParameterConstraint(name = "mobile", constraintType = {ConstraintType.NotBlank}, notBlank = @NotBlank(message = "移动电话必填"))
    })
    @RequestMapping(value = "/user", method = RequestMethod.POST)
    public String add(MonkeyDto monkeyDto) {
        userService.addUser(monkeyDto);
        return "SUCCESS:新增用户成功";
    }

    @ParameterConstraints(value = {
            @ParameterConstraint(name = "orgId", constraintType = {ConstraintType.NotBlank}, notBlank = @NotBlank(message = "所属组织必填")),
            @ParameterConstraint(name = "account", constraintType = {ConstraintType.Length},
                    length = @Length(min = 3, max = 10, message = "登录帐号的长度范围[3,10]")),
            @ParameterConstraint(name = "email", constraintType = {ConstraintType.NotBlank}, notBlank = @NotBlank(message = "邮箱必填")),
            @ParameterConstraint(name = "mobile", constraintType = {ConstraintType.NotBlank}, notBlank = @NotBlank(message = "移动电话必填"))
    })
    @RequestMapping(value = "/user", method = RequestMethod.PUT)
    public String modify(MonkeyDto monkeyDto) {
        userService.modifyUser(monkeyDto);
        return "SUCCESS:修改用户成功";
    }

    @ParameterConstraints(value = {
            @ParameterConstraint(name = "newPwd", constraintType = {ConstraintType.NotBlank}, notBlank = @NotBlank(message = "新密码必填")),
            @ParameterConstraint(name = "newPwd2", constraintType = {ConstraintType.NotBlank}, notBlank = @NotBlank(message = "确认新密码必填"))
    })
    @RequestMapping(value = "/user/rest/passwd", method = RequestMethod.PUT)
    public String restPasswd(MonkeyDto monkeyDto) {
        userService.restPasswd(monkeyDto);
        return "SUCCESS:重置用户密码成功";
    }

    @RequestMapping(value = "/user/password", method = RequestMethod.PUT)
    public MonkeyResponseDto modifyPassword(@Valid ModifyUserPasswordDto modifyUserPasswordDto, BindingResult result) {
        if (result.hasErrors()) {
            return new MonkeyResponseDto().fail(result);
        }
        return userService.modifyPassword(modifyUserPasswordDto);
    }

    @ParameterConstraint(name = "reason", constraintType = {ConstraintType.NotBlank}, notBlank = @NotBlank(message = "新密码必填"))
    @RequestMapping(value = "/user/status", method = RequestMethod.PUT)
    public String changeStatus(@RequestParam("ids") Long[] ids,
                               @RequestParam("status") UserStatus status,
                               @RequestParam("reason") String reason,
                               @CurrentUser User opUser) {
        userService.changeStatus(ids, status, reason, opUser);
        return "SUCCESS:操作成功";
    }

    @RequestMapping(value = "/users", method = RequestMethod.GET)
    public Page<User> users(Searchable searchable) {
        searchable.addSearchFilter("admin", SearchOperator.eq, false);
        return userService.findAll(searchable);
    }

    @RequestMapping(value = "/users/online", method = RequestMethod.GET)
    public MonkeyResponseDto onlineUser() {
        return userService.onlineUsers();
    }

    @RequestMapping(value = "/user/organization/{organization_id}", method = RequestMethod.GET)
    public Page<User> findUsersByOrganization(@PathVariable(value = "organization_id") Organization organization, Searchable searchable) {
        return organizationService.findUsersByOrganization(organization, searchable);
    }

    @RequestMapping(value = "/user/status_histories", method = RequestMethod.GET)
    public Page<UserStatusHistory> userStatusHistories(Searchable searchable) {
        searchable.addSort(Sort.Direction.DESC, "createTime");
        return userStatusHistoryService.findAll(searchable);
    }

    @RequestMapping(value = "/user/login_histories", method = RequestMethod.GET)
    private MonkeyResponseDto userLoginHistories(Searchable searchable) {
        Page<UserOnlineHistory> userLoginHistories = userOnlineHistoryService.findAll(searchable);
        return new LoadUserLoginHistoriesResponseJSONDto(userLoginHistories).success("load.user.login.history.success");
    }


    /**
     * 给用户授权
     *
     * @param user
     * @param menu
     * @param permissionIds
     * @return
     */
    @RequestMapping(value = "/user/menu/permission", method = RequestMethod.POST)
    public String grantPermissionToUser(
            @RequestParam(value = "userId") User user,
            @RequestParam(value = "menuId") Menu menu,
            @RequestParam(value = "permissionIds") Long[] permissionIds) {
        if (MonkeyUtils.isEmpty(user)) {
            return "FAIL:用户必填";
        }
        if (MonkeyUtils.isEmpty(menu)) {
            return "FAIL:菜单资源必填";
        }
        if (MonkeyUtils.isEmpty(permissionIds)) {
            return "FAIL:权限必填";
        }
        userService.grantPermissionToUser(user, menu, permissionIds);
        return "SUCCESS:授权成功";
    }

    /**
     * 回收用户权限
     *
     * @param user
     * @param menu
     * @param permissionIds
     * @return
     */
    @RequestMapping(value = "/user/menu/permission", method = RequestMethod.PUT)
    public String recoveryPermissionFromUser(
            @RequestParam(value = "userId") User user,
            @RequestParam(value = "menuId") Menu menu,
            @RequestParam(value = "permissionIds") Long[] permissionIds) {
        if (MonkeyUtils.isEmpty(user)) {
            return "FAIL:用户必填";
        }
        if (MonkeyUtils.isEmpty(menu)) {
            return "FAIL:菜单资源必填";
        }
        if (MonkeyUtils.isEmpty(permissionIds)) {
            return "FAIL:权限必填";
        }
        userService.recoveryPermissionFromUser(user, menu, permissionIds);
        return "SUCCESS:回收权限成功";
    }

    /**
     * 通过用户和资源查询权限
     *
     * @param user
     * @param menu
     * @return
     */
    @RequestMapping(value = "/user/menu/permission", method = RequestMethod.GET)
    public List<Permission> getPermissionByUserMenu(
            @RequestParam(value = "userId") User user,
            @RequestParam(value = "menuId") Menu menu) {
        return userService.getPermissionByUserMenu(user, menu);
    }

    /**
     * 通过用户查询权限
     *
     * @param user
     * @param pageable
     * @return
     */
    @RequestMapping(value = "/user/permission", method = RequestMethod.GET)
    public Page<UserResourcePermission> getPermissionByUser(@RequestParam(value = "userId") User user, Pageable pageable) {
        return userService.getPermissionByUser(user, pageable);
    }

    /**
     * 查询出用户的角色
     *
     * @param user
     * @return
     */
    @RequestMapping(value = "/user/role", method = RequestMethod.GET)
    public List<Role> getRolesByUser(@RequestParam(value = "userId") User user) {
        return userService.getRolesByUser(user);
    }
}
